// objectmanager.h : contains the definition of the object managing class, which can combine components
// with other aspects (scripts) to create specific "objects"
//$Id: ObjectManager.h 25 2009-08-21 02:02:10Z brwarner2 $

#pragma once
#include "types.h"

//Component manager class
class CComponentManager;
class IComponent;
class CArea;

//Object manager class
class CObjectManager
{
public:
	//Create the object manager, requires gamemonkey script machine
	CObjectManager(CComponentManager*, gmMachine*);

	//Destructor
	~CObjectManager(void);

	//Loads an object table from a file
	void LoadObjectData( const std::string& filename );
	
	//Called to register all GM functions
	void RegisterGM( void );

	//Destroys an object
	void Destroy( ObjectID );

	//Gets an object table
	gmTableObject* GetObjectTable( const std::string& name )
	{
		return m_objecttables[name];
	}

	//Releases all objects
	void Release(void);

	//Sets the area of an object
	void SetArea( ObjectID, CArea* );

	//Finds an object by its name
	ObjectID FindByName( const std::string& name );

private:
	//GameMonkey machine
	gmMachine* m_pGM;

	//Component manager
	CComponentManager* m_pCManager;

	//Internal object structure
	struct Object
	{
		//Object components
		std::list<IComponent*> components;

		//Table object
		gmTableObject* gmTable;
	};

	//Object list type
	typedef std::vector<Object*> ObjectList;

	//Object list
	ObjectList m_objects;

	//List of object tables
	std::map<std::string, gmTableObject*> m_objecttables;

	//Registered member structure
	struct RegisteredMember
	{
		std::string name; //Name of the member function
		ComponentID componentID; //ComponentID
		gmFunctionObject* func; //Function
	};

	//Registered member function list type
	typedef std::map< const gmFunctionObject* , RegisteredMember > RegistryList;

	//Registered members
	RegistryList m_members;

	//Callback for registered member functions
	static int GM_CDECL MemberCallback( gmThread* a_thread );

	//Adds member functions from a component into a table
	void CreateMembers( ComponentID, gmTableObject* );

public:

	//Pushes the object table onto the stack
	void PushObject( gmThread*, ObjectID );

	//Gets an object table
	gmTableObject* GetObjectTable( ObjectID );

	//Creates an object
	ObjectID CreateObject( const std::string& id, const ParameterList& params, CArea* );

	//Sends a message to an object
	void Message( ObjectID, MessageID, const boost::any& arg = 0 );

	//Gets a component from an object
	IComponent* GetComponent( ObjectID, ComponentID );

	//Calls a hook on an object
	void CallHook( ObjectID, const std::string& name, 
		gmVariable arg1 = gmVariable::s_null, gmVariable arg2 = gmVariable::s_null, gmVariable arg3 = gmVariable::s_null, gmVariable arg4 = gmVariable::s_null );

	//Registers a GM member function for a component
	void RegisterMemberFunction( ComponentID, const std::string& name );

	//Broadcasts a message to all objects
	void Broadcast( MessageID, const boost::any& arg = 0 );
};
